import { _decorator, Node, ProgressBar, Label, v3 } from 'cc';
import { BasePanel } from '../../../../scripts/libs/ui/BasePanel';
import { gm } from '../../../../scripts/managers/GameManager';
import { LaunchConfig } from '../../../../Launch/LaunchConfig';
import { TweenToStart } from '../../../../scripts/libs/rxjs/cc3/TweenStart';
import { instantFunc } from '../../../../scripts/libs/rxjs/cc3/CommonObservable';
import { concat, forkJoin, Observable, of, Subscription } from 'rxjs';
import { LoadingPanelMode } from '../../../../scripts/managers/Enums';
import { MergeASAP } from '../../../../scripts/libs/rxjs/cc3/Merge';
import { lm } from '../../LobbyManager';
import { Timer } from '../../../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { nullifySubscription } from '../../../../scripts/libs/rxjs/utils';
import { misc_sdk_m } from '../../../../scripts/managers/SDK/MiscSDKManager';
import { sys } from 'cc';
import { BUILD_NUMBER, SHORT_COMMIT_HASH } from '../../../../scripts/ConfigConst';
import { UIOpacity } from 'cc';
import { linear, linearClamp } from '../../../../scripts/libs/utils/math';
import { Vec3 } from 'cc';
import { thinking_sdk_m } from '../../../../scripts/managers/SDK/ThinkingCocosSDKManager';
const { ccclass, property } = _decorator;

const _v30 = v3();

@ccclass('LoadingPanel')
export class LoadingPanel extends BasePanel {

    /**
     * 使用时，先设定Mode，一般为 LoadingPanelMode.Default(从0~100%)
     * 修改gm.maxProgressValue,再设定gm.curProgressValue.value即可观察到变化
     */

    @property(Node)
    bgNode: Node = null;

    @property(Node)
    bg1Node: Node = null;

    @property(ProgressBar)
    progressBar: ProgressBar = null;

    @property(Label)
    progressLabel: Label = null;

    @property(Node)
    loadingIndicator: Node = null;

    @property(Node)
    logoNode: Node = null;

    @property(Label)
    versionLabel: Label = null;

    @property(Node)
    windmillNode: Node = null;

    useObserves() {
        return [
            MergeASAP(gm.curProgressValue, gm.curProgressValue2).subscribe(this.refresh.bind(this)),
            MergeASAP(
                lm.loadingAssets, lm.hotupdating
            ).subscribe(_ => {
                this.log('loadingAssets, hotupdating', lm.loadingAssets.value, lm.hotupdating.value);
                let showProgressBar = [lm.loadingAssets.value, lm.hotupdating.value].some(_ => _);
                this.progressBar.node.active = showProgressBar;
                this.logoNode.active = showProgressBar;
                this.bgNode.active = showProgressBar;
                this.bg1Node.active = !showProgressBar;
            }),
            MergeASAP(
                lm.customLoadingReasons
            ).subscribe(_ => {
                let show = lm.customLoadingReasons.size > 0;
                this.loadingIndicator.active = show;
            }),

            misc_sdk_m.infoDic.subscribe(this.refreshVersion.bind(this)),
        ];
    }

    refreshVersion() {
        if (sys.isNative) {
            let nativeVersion = misc_sdk_m.getNativeVersion();
            this.versionLabel.string = `Version:${nativeVersion} Build:${misc_sdk_m.getNativeBuild()}`;

            thinking_sdk_m.requestSetSuperProperties({
                GameVersion: nativeVersion
            });

        } else {
            this.versionLabel.string = `Build:${BUILD_NUMBER} Hash:${SHORT_COMMIT_HASH}`;
        }
    }

    refresh() {
        const v = Math.min(gm.curProgressValue.value + gm.curProgressValue2.value, gm.maxProgressValue);
        let progressValue = 0;
        switch (gm.loadingPanelMode) {
            case LoadingPanelMode.FirstTime: {
                // this.progressLabel.string = `加载中... ${Math.round(v / gm.maxProgressValue * 100 * (1 - LaunchConfig.launch.firstProgressRateMax) + (LaunchConfig.launch.firstProgressRateMax * 100))}%`;
                progressValue = v / gm.maxProgressValue * (1 - LaunchConfig.launch.firstProgressRateMax) + LaunchConfig.launch.firstProgressRateMax;
                // this.progressBar.progress = progressValue;
                this.animProgressValueTo(progressValue);
                break;
            }
            case LoadingPanelMode.Default: {
                // this.progressLabel.string = `加载中... ${Math.round(v / gm.maxProgressValue * 100)}%`;
                progressValue = v / gm.maxProgressValue;
                // this.progressBar.progress = progressValue;
                this.animProgressValueTo(progressValue);
                break;
            }
        }
        // this.progressLabel.string = `LOADING...${Math.round(progressValue * 100)}%`;
    }

    _sub_anim_progressValueTo: Subscription = null;
    animProgressValueTo(targetValue: number) {
        nullifySubscription.call(this, '_sub_anim_progressValueTo');
        this._sub_anim_progressValueTo = TweenToStart(this, .1, { progressValue: targetValue }).subscribe();
    }

    private _progressValue: number = 0;
    public get progressValue(): number { return this._progressValue; }
    public set progressValue(v: number) {
        this._progressValue = v;
        this.progressBar.progress = v;
        this.progressLabel.string = `LOADING...${Math.round(v * 100)}%`;

        // this.logoNode.getComponent(UIOpacity).opacity = linearClamp(0, .1, 0, 255, v);

        let windmillX = linear(0, 1, -400, 400, v);
        windmillX = Math.min(400 - 14, windmillX);
        this.windmillNode.setPosition(v3(windmillX, 3, 0));
        // this.logoNode.setPosition(Vec3.lerp(_v30, v3(0, 300, 0), v3(0, 353, 0), v));
    }

    static openCount = 0;

    // willOpen(): Observable<any> {
    //     return forkJoin([
    //         TweenToStart(this.logoNode, 1, { position: v3(0, 353, 0) }, { easing: 'expoOut' }),
    //         TweenToStart(this.logoNode.getComponent(UIOpacity), 1, { opacity: 255 }, { easing: 'linear' }),
    //     ]);
    // }

    afterOpen() {
        LoadingPanel.openCount++;
        return of('afterOpen');
    }

    openPanelAnim(): Observable<any> {
        if (LoadingPanel.openCount == 0) {
            return instantFunc(() => this.ensureUIOpacity().opacity = 255);
        } else {
            if (![lm.loadingAssets.value, lm.hotupdating.value].some(_ => _)) { // 这里的原因不用延迟出现，为的是自定义的加载覆盖，遮罩界面需要延迟出现
                return concat(
                    Timer(.2, this.node),
                    TweenToStart(this.ensureUIOpacity(), .2, { opacity: 200 }, { easing: 'expoOut' })
                );
            };
            return TweenToStart(this.ensureUIOpacity(), .2, { opacity: 255 }, { easing: 'expoOut' });
        }
    }

    closePanelAnim(): Observable<any> {
        this.ensureUIOpacity();
        return TweenToStart(this.ensureUIOpacity(), .2, { opacity: 0 }, { easing: 'expoIn' })
    }
}


